home *** CD-ROM | disk | FTP | other *** search
- ///////////////////////////////////////////////////////////////////////////////
- // FILENAME: eTAudioComponent.h
- // SUMMARY: Implementation for a container of audio data.
- // SUPERCLASS: Object
- // INTERFACE: None, but it "exports" eTAudioComponentIcon and IconH.
- // PROTOCOLS: <ComponentData,
- // ETFDSupport,HTMDSupport,LaTeXSupport>
- // AUTHOR: Rohit Khare
- // COPYRIGHT: (c) 1994 California Institure of Technology, eText Project
- ///////////////////////////////////////////////////////////////////////////////
- // IMPLEMENTATION COMMENTS
- // This is a subclass that externalizes audio components. Manages
- // a Sound object. useSound:... has been included to allow passing
- // in Sounds that are not on disk (as with paste:s)
- // We eventually want to support WAV and AIFF types (which NX Sound
- // does not. Perhaps adopt SOX code (talk to nick christopher)?
- ///////////////////////////////////////////////////////////////////////////////
- // HISTORY
- // 07/14/94: Created. Aliases the NeXTSTEP Sound API.
- ///////////////////////////////////////////////////////////////////////////////
-
- #import "eTAudioComponent.h"
- #define _eTAudioComponentVERSION 10
-
- @implementation eTAudioComponent
- // id theSound;
-
- - theSound
- { if (!theSound) theSound = [[Sound alloc] init];
- return theSound;
- }
- + newSoundNamed:(const char *)theName
- {
- // This is a fake implementation. see eTImageComponent for a real one.
- id newObj;
-
- newObj = [[eTAudioComponent alloc] initInDoc:nil linked:NO];
- theSound = [Sound findSoundFor:theName];
- componentName = NXUniqueString(theName);
- return newObj;
- }
- - useSound:(Sound *)newSound
- name:(const char *) newComponentName
- path:(const char *) newCurrentPath
- {
- theSound = newSound;
- componentName = NXUniqueString(newComponentName);
- currentPath = NXUniqueString(newCurrentPath);
- shouldEdit &= !isLinked; // should we ever muck with linked snds?
- return self;
- }
-
- - readComponentFromPath:(NXAtom)newPath
- {
- [super readComponentFromPath:newPath];
- // attempt to load from currentPath
- theSound = nil;
- if (currentPath && *currentPath) {
- theSound = [[Sound alloc] initFromSoundfile:currentPath];
- shouldEdit &= !isLinked; // should we ever muck with linked snds?
- }
- if (!theSound){
- theSound = [Sound findSoundFor:"SystemBeep"];
- shouldEdit = NO;
- }
- return self;
- }
- - writeComponentToPath:(NXAtom)path inFormat:(int) theFormat
- {
- const char *tmp;
- char target[MAXPATHLEN];
- id altSound;
-
- switch(theFormat) {
- case ETFD_FMT:
- // if it's not (a link) or (clean and the target is found),
- // if the (source is found and it's clean), copy
- // else write.
- sprintf(target,"%s/%s",path,componentName);
- if (!((isLinked) || ((!isDirty) && (!access(target,F_OK|R_OK))))){
- if ((!isDirty) && *currentPath &&
- (!access(currentPath, F_OK|R_OK))) {
- // copy
- char cmd[2*MAXPATHLEN];
-
- sprintf(cmd,"cp -rp \"%s\" \"%s\"", currentPath, target);
- system(cmd);
- currentPath = NXUniqueString(target);
- } else {
- if (!rindex(target, '.') ||
- strcasecmp(".snd", rindex(target, '.')))
- strcat(target, ".snd");
- [theSound writeSoundfile:target];
- currentPath = NXUniqueString(target);
- componentName = NXUniqueString(rindex(target,'/')+1);
- }
- isDirty=NO;
- }
- [etDoc registerComponent:componentName];
- break;
-
- case HTMD_FMT:
- case TeXD_FMT:
- // Always is an .au. If it doesn't exist, copy an .au or create one.
- if (componentName) tmp = componentName;
- else if ([theSound name]) tmp = [theSound name];
- else tmp = [[self class] name];
-
- sprintf(target,"%s/%s",path,tmp);
- if (!rindex(target, '.') || strcasecmp(".au", rindex(target, '.')))
- strcat(target, ".au");
- if (access(target,F_OK|R_OK) || isDirty) {
- // if currentPath is an .au, copy.
- if (rindex(currentPath, '.') &&
- (!strcasecmp(".au", rindex(currentPath, '.'))) &&
- (!access(currentPath,F_OK|R_OK))) {
- char cmd[2*MAXPATHLEN];
-
- sprintf(cmd,"cp -rp \"%s\" \"%s\"", currentPath, target);
- system(cmd);
- } else {
- altSound = [[Sound alloc] init];
- [altSound copySound:theSound];
- [altSound convertToFormat:SND_FORMAT_MULAW_8
- samplingRate:SND_RATE_CODEC
- channelCount:1];
- [altSound writeSoundfile:target];
- altSound = [altSound free];
- }
- }
- [etDoc registerComponent:rindex(target,'/')+1];
- break;
- }
- return self;
- }
- - writeComponentToPboard:thePboard
- {
- [thePboard declareTypes:&NXSoundPboard num:1 owner:nil];
- [theSound writeToPasteboard:thePboard];
- // here we copy code from the superclass because of the order of
- // addTypes: calls and the preference-order of Pasteboard
- [thePboard addTypes:&NXFilenamePboardType num:1 owner:nil];
- [thePboard writeType:NXFilenamePboardType
- data:currentPath length:strlen(currentPath)];
- return self;
- }
- - addToPboard:pboard
- {
- NXStream *memstream;
-
- memstream = NXOpenMemory(NULL, 0, NX_READWRITE);
- if (memstream) {
- [theSound writeSoundToStream:memstream];
- [pboard addTypes:&NXSoundPboardType num:1 owner:nil];
- [pboard writeType:NXSoundPboardType fromStream:memstream];
- NXCloseMemory(memstream, NX_FREEBUFFER);
- }
- return self;
- }
- - readComponentFromPboard:thePboard
- {
- [super readComponentFromPboard:thePboard];
- // ok, so now we have a quasi-valid entry in currentPath
- // If the sound can init from thePboard, go right ahead.
-
- theSound = [[Sound alloc] initFromPasteboard:thePboard];
- if (!theSound) {
- //ok, there's no NXSoundPboardType data. Can we get a file?
- if (currentPath && *currentPath) {
- theSound = [[Sound alloc] initFromSoundfile:currentPath];
- }
- shouldEdit &= !isLinked; // should we ever muck with linked snds?
- if (!theSound){
- theSound = [Sound findSoundFor:"SystemBeep"];
- shouldEdit = NO;
- }
- }
- // special case: If we paste raw audio data and there's no path,
- // componentName is currently "Untitled-%d"; we need to cat ".snd"
- if (!(currentPath && *currentPath)) {
- char tmp[MAXPATHLEN]; // hey, it's only stack space... :)
-
- strcpy(tmp, componentName);
- if (!rindex(tmp, '.') || strcasecmp(".snd", rindex(tmp, '.')))
- strcat(tmp, ".snd");
- componentName = NXUniqueString(tmp);
- }
-
- return self;
- }
-
- - readRichText:(NXStream *)stream forView:view
- {
- [super readRichText:stream forView:view];
- if (currentPath && *currentPath) {
- theSound = [[Sound alloc] initFromSoundfile:currentPath];
- }
- shouldEdit &= !isLinked; // should we ever muck with linked snds?
- if (!theSound){
- theSound = [Sound findSoundFor:"SystemBeep"];
- shouldEdit = NO;
- }
- return self;
- }
- - writeRichText:(NXStream *)stream forView:view
- {
- // since this method is called before any writeComponents, we attempt
- // to precompute whether an extension will be added
-
- char target[MAXPATHLEN];
-
- /*if (!etDoc)*/ etDoc = [view etDoc]; // Always reset; bugfix for shared audio, 12/23
- strcpy(target, componentName);
- if (!rindex(target, '.') || strcasecmp(".snd", rindex(target, '.'))) {
- strcat(target, ".snd");
- componentName = NXUniqueString(target);
- }
- return [super writeRichText:stream forView:view];
- }
- - writeHTML:(NXStream *)stream forView:view
- {return [self writeHTML:stream forView:view andClose:YES];}
- - writeHTML:(NXStream *)stream forView:view andClose:(BOOL)closeIt
- {
- const char *tmp;
-
- /*if (!etDoc)*/ etDoc = [view etDoc]; // Always reset; bugfix for shared audio, 12/23
- if (componentName) tmp = componentName;
- else if ([theSound name]) tmp = [theSound name];
- else tmp = [[self class] name];
-
- NXPrintf(stream, "<A HREF=\"%V%V\">",tmp,
- ((!rindex(tmp, '.') || strcmp(".au", rindex(tmp, '.')))?".au":""));
- if (closeIt) {
- NXPrintf(stream, "%v</A>",tmp);
- }
- return self;
- }
-
- - writeLaTeX:(NXStream *)stream forView:view
- {
- const char *tmp;
-
- /*if (!etDoc)*/ etDoc = [view etDoc]; // Always reset; bugfix for shared images, 12/23
- if (componentName) tmp = componentName;
- else if ([theSound name]) tmp = [theSound name];
- else tmp = [[self class] name];
- NXPrintf(stream, "\n\\footnote{A reference to the sound %w%w}",
- tmp,((!rindex(tmp, '.') || strcmp(".au", rindex(tmp, '.')))?".au":""));
- return self;
- }
- @end